package com.monitor.methods.tcpmethod;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import com.monitor.methods.TCPMethod;
import com.monitor.persistence.Port;

public class Scan implements Runnable {

	private int start;
	private int stop;
	private InetAddress address;
	private int MAX_TIMEOUT = 3;
	private Map<Integer, Integer> timeoutsMap = new HashMap<Integer, Integer>();
	private List<Port> values;

	public Scan(int start, int stop, InetAddress address,
			List<Port> map) {
		super();
		this.start = start;
		this.stop = stop;
		this.address = address;
		this.values = map;
	}

	@Override
	public void run() {
		for (int i = start; i < stop; i++) {
			timeoutsMap.put(i, 0);
			Port openPort = scan(i);
			if(openPort != null) {
				values.add(openPort);
			}
			System.out.println(i);
		}
		TCPMethod.signThreadStopped();
	}

	private Port scan(int i) {
		Port port = null;
		try {
			// System.out.println(i);
			Socket socket = new Socket(address, i);
			socket.setSoTimeout(500);
			port = new Port(i);
			Scanner in = new Scanner(socket.getInputStream());
			PrintWriter out = new PrintWriter(socket.getOutputStream());
			out.print("CONNECT");
			out.flush();
			socket.shutdownOutput();
			while(in.hasNextLine()) {
				String line = in.nextLine();
				try {
					Integer.parseInt(line.substring(0, 2));
				} catch(NumberFormatException e) {
					port.setService(line);
					break;
				}
				port.setService(line.substring(3));
				System.err.println(line);
				break;
			}
			socket.close();
		} catch (SocketTimeoutException e) {
			Integer timeout = timeoutsMap.get(i);
			if (timeout <= MAX_TIMEOUT) {
				try {
					Thread.sleep(2500);
				} catch (Exception f) {
				}
				timeoutsMap.put(i, ++timeout);
				return this.scan(i);
			}
			return null;
		} catch (UnknownHostException e) {
			return null;
		} catch (IOException e) {
			return null;
		}

		return port;
	}
}
